package net.csdn.business.facade;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.csdn.business.common.domain.request.OrgInfoReqDto;
import net.csdn.business.common.domain.request.OrgMemberDto;
import net.csdn.business.common.domain.request.UserRegMigrateDto;
import net.csdn.business.common.domain.request.org.OrgInviteMemberDto;
import net.csdn.business.common.domain.vo.OrgInfoVo;
import net.csdn.business.common.domain.vo.OrgMemeberVo;
import net.csdn.business.common.domain.vo.UserVo;
import net.csdn.business.common.enums.ProjectEnum;
import net.csdn.business.common.enums.ResultCodeEnum;
import net.csdn.business.common.exception.BusinessException;
import net.csdn.business.common.utils.JsonUtil;
import net.csdn.business.pojo.AtomGitGroupMember;
import net.csdn.business.pojo.AtomGitUser;
import net.csdn.business.util.ListDivider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Component
public class UserFacade {

    private final MigrateFacade migrateFacade;

    @Value("${grpc.atomgit.anonymous:65f906eb7af38bb6ff80fXXX}")
    private String anonymous;
    @Value("${grpc.atomgit.defaultChannel:gitee}")
    private String defaultChannel;
    @Value("${grpc.atomgit.threadPoolSize:5}")
    private Integer threadPoolSize;



    public Integer registerForMigrate(List<AtomGitUser> userListList) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
        Integer totalSum = 0;
        List<List<AtomGitUser>> lists = ListDivider.divideList(userListList,threadPoolSize);
        List<Future<Integer>> futures = new ArrayList<>();
        for (List<AtomGitUser> userList: lists) {
            Callable<Integer> task = () ->{
                 return regsiterForMigrateThread(userList);
            };
            futures.add(executorService.submit(task));
        }
        // 等待所有线程执行结束并计算总和
        for (Future<Integer> future : futures) {
            totalSum += future.get();
        }
        executorService.shutdown();
        return totalSum;
    }

    public Integer regsiterForMigrateThread(List<AtomGitUser> userListList){
        AtomicReference<Integer> succesNum = new AtomicReference<>(0);
        userListList.forEach(user->{
            UserRegMigrateDto userRegMigrateDto = new UserRegMigrateDto();
            userRegMigrateDto.setName(user.getName());
            userRegMigrateDto.setUsername(user.getUserName());
            userRegMigrateDto.setNickname(user.getName());
            //避免用户信息为空的情况
            userRegMigrateDto.setEmail(ObjectUtils.isEmpty(user.getEmail())?user.getUserName()+"@atomgit.com":user.getEmail());
            userRegMigrateDto.setPhone(user.getPhone());
            userRegMigrateDto.setExternalId(String.valueOf(user.getId()));
            //默认的渠道
            userRegMigrateDto.setChannel(defaultChannel);
            try {
                //插入用户
                registerForMigrate(userRegMigrateDto);
                succesNum.getAndSet(succesNum.get() + 1);
            } catch (Exception e) {
                log.error("registerForMigrate userRegMigrateDto:{} error:{}", JsonUtil.toJsonString(userRegMigrateDto), JsonUtil.toJsonString(e));
            }
        });
        return succesNum.get();
    }

    public UserVo registerForMigrate(UserRegMigrateDto userRegMigrateDto) throws Exception {
        log.info("==== 用户注册,userRegMigrateDto={}", JSON.toJSONString(userRegMigrateDto));
        //UserVo userVo = userFeignClient.registeForMigrate(userRegMigrateDto);
        UserVo userVo =null;
        return userVo;
    }


    public String queryForMigrateUser(AtomGitUser user){
        UserRegMigrateDto userRegMigrateDto = new UserRegMigrateDto();
        userRegMigrateDto.setName(user.getName());
        userRegMigrateDto.setUsername(user.getUserName());
        userRegMigrateDto.setNickname(user.getName());
        //避免用户信息为空的情况
        userRegMigrateDto.setEmail(user.getEmail());
        userRegMigrateDto.setPhone(user.getPhone());
        userRegMigrateDto.setExternalId(String.valueOf(user.getId()));
        //userFeignClient.queryForMigrate(userRegMigrateDto);
        return "";
    }


    public String queryForMigrateUser(UserRegMigrateDto userRegMigrateDto){
        //userFeignClient.queryForMigrate(userRegMigrateDto)
        return "";
    }


    public UserVo queryUserByEmail(String email){
        //userFeignClient.getUserByEmail(email)
        return new UserVo();
    }

    public int inviteMemberAdd(OrgInviteMemberDto inviteMemberDto){
        //orgFeignClient.inviteMemberAdd(inviteMemberDto);
        return 1;
    }


    public String getOrgAdmin(String orgId,String groupName){
        OrgInfoReqDto orgInfoReqDto = new OrgInfoReqDto();
        orgInfoReqDto.setOrgId(orgId);
        orgInfoReqDto.setOrgCode(groupName);
        //List<String> admin = orgFeignClient.getAdmin(orgInfoReqDto);
        List<String> admin =null;
        return !CollectionUtils.isEmpty(admin)?admin.get(0): anonymous;
    }

    public OrgInfoVo getOrgInfo(String path){
        //return orgFeignClient.getByPath(path);
        return new OrgInfoVo();
    }


    public String getAdminUserIdByProjectId(String repoGroupName,String repoName){
        /*ProjectVo projectVo = migrateFacade.getProjectDetailByPath(repoGroupName + "/" + repoName);
        AtomicReference<Integer> succesNum = new AtomicReference<>(0);
        if(ObjectUtils.isEmpty(projectVo)){
            throw new BusinessException(ResultCodeEnum.RESOURCE_NOT_EXIST);
        }
        List<UserProjectRoleVo> list= getProjectUser(projectVo.getId());
        List<UserProjectRoleVo> managers = list.stream().filter(userProjectRoleVo -> userProjectRoleVo.getAccessLevel() == ProjectEnum.AccessLevelEnum.MANAGER.getCode()).collect(Collectors.toList());
        return CollectionUtils.isNotEmpty(managers)?managers.get(0).getExternUid(): anonymous;*/
        return "";
    }


    public String getAdminUserIdByProjectId(Long projectId){
       /* List<UserProjectRoleVo> list= getProjectUser(projectId);
        List<UserProjectRoleVo> managers = list.stream().filter(userProjectRoleVo -> userProjectRoleVo.getAccessLevel() == ProjectEnum.AccessLevelEnum.MANAGER.getCode()).collect(Collectors.toList());

        return CollectionUtils.isNotEmpty(managers)?managers.get(0).getExternUid(): anonymous;*/
        return "";
    }


    public Integer importAtomGitGroupMemberExcutor(List<AtomGitGroupMember> gitGroupMembers, Map<String,String> orgAdminmap) throws Exception{
        ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
        Integer totalSum = 0;
        List<List<AtomGitGroupMember>> lists = ListDivider.divideList(gitGroupMembers,threadPoolSize);
        List<Future<Integer>> futures = new ArrayList<>();
        for (List<AtomGitGroupMember> userList: lists) {
            Callable<Integer> task = () ->{
                return importAtomGitGroupMemberThread(userList,orgAdminmap);
            };
            futures.add(executorService.submit(task));

        }
        // 等待所有线程执行结束并计算总和
        for (Future<Integer> future : futures) {
            totalSum += future.get();
        }
        executorService.shutdown();
        return totalSum;
    }

    public Integer importAtomGitGroupMemberThread(List<AtomGitGroupMember> list, Map<String,String> orgAdminmap){
        AtomicReference<Integer> succesNum = new AtomicReference<>(0);
        list.forEach(member->{
            OrgInviteMemberDto inviteMemberDto = new OrgInviteMemberDto();
            try {
                String groupName = member.getGroupName().toLowerCase();
                String adminUserId = orgAdminmap.get(groupName);
                AtomGitUser user = member.getUser();
                Long accessLevel = member.getAccessLevel();
                ProjectEnum.AccessLevelEnum accessLevelEnum = ProjectEnum.AccessLevelEnum.ofCode(accessLevel.intValue());
                //获取用户id
                String userId = queryForMigrateUser(user);
                if(StringUtils.isBlank(userId)){
                    throw new BusinessException(ResultCodeEnum.RESOURCE_NOT_EXIST);
                }
                inviteMemberDto.setUserId(userId);
                inviteMemberDto.setInviterId(adminUserId);
                inviteMemberDto.setOrgCode(groupName);
                inviteMemberDto.setRoleCode(accessLevelEnum.getDesc());
                inviteMemberAdd(inviteMemberDto);
                succesNum.set(succesNum.get()+1);
            } catch (IllegalArgumentException e) {
                log.error("IllegalArgumentException member:{} error:{}", JsonUtil.toJsonString(inviteMemberDto), JsonUtil.toJsonString(e));
            } catch (Exception e) {
                log.error("Exception member:{} error:{}", JsonUtil.toJsonString(inviteMemberDto), JsonUtil.toJsonString(e));
            }
        });
        return succesNum.get();
    }


    public Integer importAtomGitGroupMember(List<AtomGitGroupMember> gitGroupMembers) throws Exception{

        Set<String> groupNames = gitGroupMembers.stream().map(AtomGitGroupMember::getGroupName).map(i->i.toLowerCase()).collect(Collectors.toSet());
        Map<String,Boolean> groupMap = Maps.newHashMap();
        Map<String,String> orgAdminmap = Maps.newHashMap();
        groupNames.forEach(group->{
            try {
                groupMap.put(group,false);
                OrgInfoVo orgInfoVo = getOrgInfo(group);
                if(!ObjectUtils.isEmpty(orgInfoVo)){
                    groupMap.put(group,true);
                    String orgAdmin = getOrgAdmin("", group);
                    orgAdminmap.put(group,orgAdmin);
                }
            } catch (Exception e) {
                log.error("getByPath error path:{},error:{}",group,JsonUtil.toJsonString(e));
            }
        });
        List<AtomGitGroupMember> collect = gitGroupMembers.stream().
                filter(member -> groupMap.get(member.getGroupName().toLowerCase())).collect(Collectors.toList());
        return importAtomGitGroupMemberExcutor(collect,orgAdminmap);
    }

    public List<Long> checkAtomGitUser(List<Long> ids, String channel){
        /*List<Long> list = userFeignClient.queryForMigrateResult(ids,channel);
        // 查询差集
        List difference = ListDivider.getDifference(ids, list);
        return difference;*/
        return Lists.newArrayList();
    }

    public List<AtomGitGroupMember> CheckAtomGitGroupMember(List<AtomGitGroupMember> list){
        List<AtomGitGroupMember> result = Lists.newArrayList();
        //获取这个组下所有的成员关系
        Map<String, List<AtomGitGroupMember>> mapMemebers = list.stream().collect(Collectors.groupingBy(AtomGitGroupMember::getGroupName));
        mapMemebers.forEach((k,v)->{
            //获取所有成员
            List<OrgMemeberVo> orgMemeberVos = queryOrgMemebers(k);
            Set<String> userNameAndCode = orgMemeberVos.stream().map(i -> {
                return (i.getUserName() + "_" + i.getRoleCode()).toLowerCase();
            }).collect(Collectors.toSet());
            //判断用户是否在组织下，判断授权关系
            v.forEach(atomGitGroupMember -> {
                ProjectEnum.AccessLevelEnum accessLevelEnum = ProjectEnum.AccessLevelEnum.ofCode(new Long(atomGitGroupMember.getAccessLevel()).intValue());
                    String key = atomGitGroupMember.getUser().getUserName()+ "_" +accessLevelEnum.getDesc();
                    if(StringUtils.isNotBlank(key) && !userNameAndCode.contains(key.toLowerCase())){
                        result.add(atomGitGroupMember);
                    }
            });
        });
        return result;
    }

    //获取组织下左右的用户
    public List<OrgMemeberVo> queryOrgMemebers(String orgName){
        List<OrgMemeberVo> list = Lists.newArrayList();
        OrgMemberDto query = new OrgMemberDto();
        query.setOrgCode(orgName.toLowerCase());
        query.setSize(20);
        //Page<OrgMemeberVo> orgMember = orgFeignClient.getOrgMember(query);
       /* list.addAll(orgMember.getRecords());
        while(orgMember.hasNext()){
            query.setPage((int) (orgMember.getCurrent()+1));
            orgMember = orgFeignClient.getOrgMember(query);
            list.addAll(orgMember.getRecords());
        }*/
        return list;
    }

}
